package com.datagateway.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 性能优化器组件
 * 负责系统性能监控、调优和优化建议
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class PerformanceOptimizer {

    private static final Logger logger = LoggerFactory.getLogger(PerformanceOptimizer.class);

    @Autowired
    private AlertManager alertManager;

    @Autowired
    private SystemMonitor systemMonitor;

    /**
     * 性能指标统计
     */
    private final AtomicLong totalGcCount = new AtomicLong(0);
    private final AtomicLong totalGcTime = new AtomicLong(0);
    private final AtomicLong totalCpuTime = new AtomicLong(0);
    private final AtomicLong totalThreadCount = new AtomicLong(0);

    /**
     * 性能阈值配置
     */
    private static final double MEMORY_USAGE_WARN_THRESHOLD = 80.0;
    private static final double MEMORY_USAGE_CRITICAL_THRESHOLD = 90.0;
    private static final double GC_TIME_WARN_THRESHOLD = 10.0; // 10%
    private static final double GC_TIME_CRITICAL_THRESHOLD = 20.0; // 20%
    private static final int THREAD_COUNT_WARN_THRESHOLD = 200;
    private static final int THREAD_COUNT_CRITICAL_THRESHOLD = 500;

    /**
     * 性能监控 - 每60秒执行一次
     */
    @Scheduled(fixedDelay = 60000)
    public void monitorPerformance() {
        try {
            // 监控内存使用情况
            monitorMemoryPerformance();
            
            // 监控GC性能
            monitorGcPerformance();
            
            // 监控线程性能
            monitorThreadPerformance();
            
            // 监控CPU性能
            monitorCpuPerformance();
            
            // 生成性能优化建议
            generateOptimizationSuggestions();
            
        } catch (Exception e) {
            logger.error("性能监控异常", e);
            alertManager.sendSystemErrorAlert("性能监控异常", e.getMessage());
        }
    }

    /**
     * 监控内存性能
     */
    private void monitorMemoryPerformance() {
        try {
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            MemoryUsage heapMemory = memoryBean.getHeapMemoryUsage();
            MemoryUsage nonHeapMemory = memoryBean.getNonHeapMemoryUsage();
            
            long usedHeap = heapMemory.getUsed();
            long maxHeap = heapMemory.getMax();
            long usedNonHeap = nonHeapMemory.getUsed();
            
            double heapUsagePercent = (double) usedHeap / maxHeap * 100;
            
            logger.debug("内存性能监控: 堆内存使用率={:.2f}%, 堆内存使用={} MB, 非堆内存使用={} MB", 
                        heapUsagePercent, usedHeap / 1024 / 1024, usedNonHeap / 1024 / 1024);
            
            // 内存使用率告警
            if (heapUsagePercent > MEMORY_USAGE_CRITICAL_THRESHOLD) {
                alertManager.sendMemoryUsageAlert(usedHeap, maxHeap, heapUsagePercent);
            } else if (heapUsagePercent > MEMORY_USAGE_WARN_THRESHOLD) {
                alertManager.sendMemoryUsageAlert(usedHeap, maxHeap, heapUsagePercent);
            }
            
        } catch (Exception e) {
            logger.error("监控内存性能失败", e);
        }
    }

    /**
     * 监控GC性能
     */
    private void monitorGcPerformance() {
        try {
            List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
            
            long totalGcCount = 0;
            long totalGcTime = 0;
            
            for (GarbageCollectorMXBean gcBean : gcBeans) {
                totalGcCount += gcBean.getCollectionCount();
                totalGcTime += gcBean.getCollectionTime();
            }
            
            // 计算GC时间占比
            long uptime = ManagementFactory.getRuntimeMXBean().getUptime();
            double gcTimePercent = uptime > 0 ? (double) totalGcTime / uptime * 100 : 0;
            
            logger.debug("GC性能监控: GC次数={}, GC总时间={} ms, GC时间占比={:.2f}%", 
                        totalGcCount, totalGcTime, gcTimePercent);
            
            // GC性能告警
            if (gcTimePercent > GC_TIME_CRITICAL_THRESHOLD) {
                alertManager.sendPerformanceAlert("GC时间占比", gcTimePercent, GC_TIME_CRITICAL_THRESHOLD);
            } else if (gcTimePercent > GC_TIME_WARN_THRESHOLD) {
                alertManager.sendPerformanceAlert("GC时间占比", gcTimePercent, GC_TIME_WARN_THRESHOLD);
            }
            
            // 更新统计
            this.totalGcCount.set(totalGcCount);
            this.totalGcTime.set(totalGcTime);
            
        } catch (Exception e) {
            logger.error("监控GC性能失败", e);
        }
    }

    /**
     * 监控线程性能
     */
    private void monitorThreadPerformance() {
        try {
            ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
            int threadCount = threadBean.getThreadCount();
            int peakThreadCount = threadBean.getPeakThreadCount();
            long totalStartedThreadCount = threadBean.getTotalStartedThreadCount();
            
            logger.debug("线程性能监控: 当前线程数={}, 峰值线程数={}, 总启动线程数={}", 
                        threadCount, peakThreadCount, totalStartedThreadCount);
            
            // 线程数告警
            if (threadCount > THREAD_COUNT_CRITICAL_THRESHOLD) {
                alertManager.sendPerformanceAlert("线程数量", threadCount, THREAD_COUNT_CRITICAL_THRESHOLD);
            } else if (threadCount > THREAD_COUNT_WARN_THRESHOLD) {
                alertManager.sendPerformanceAlert("线程数量", threadCount, THREAD_COUNT_WARN_THRESHOLD);
            }
            
            // 更新统计
            this.totalThreadCount.set(threadCount);
            
        } catch (Exception e) {
            logger.error("监控线程性能失败", e);
        }
    }

    /**
     * 监控CPU性能
     */
    private void monitorCpuPerformance() {
        try {
            ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
            
            if (threadBean.isThreadCpuTimeSupported()) {
                long totalCpuTime = 0;
                long[] threadIds = threadBean.getAllThreadIds();
                
                for (long threadId : threadIds) {
                    long cpuTime = threadBean.getThreadCpuTime(threadId);
                    if (cpuTime > 0) {
                        totalCpuTime += cpuTime;
                    }
                }
                
                logger.debug("CPU性能监控: 总CPU时间={} ms", totalCpuTime / 1_000_000);
                
                // 更新统计
                this.totalCpuTime.set(totalCpuTime);
            }
            
        } catch (Exception e) {
            logger.error("监控CPU性能失败", e);
        }
    }

    /**
     * 生成性能优化建议
     */
    private void generateOptimizationSuggestions() {
        try {
            // 获取当前性能指标
            PerformanceMetrics metrics = getCurrentPerformanceMetrics();
            
            // 生成优化建议
            List<OptimizationSuggestion> suggestions = analyzePerformanceAndGenerateSuggestions(metrics);
            
            // 记录优化建议
            if (!suggestions.isEmpty()) {
                logger.info("性能优化建议: {}", suggestions.size());
                for (OptimizationSuggestion suggestion : suggestions) {
                    logger.info("优化建议: {} - {}", suggestion.getType(), suggestion.getDescription());
                }
            }
            
        } catch (Exception e) {
            logger.error("生成性能优化建议失败", e);
        }
    }

    /**
     * 获取当前性能指标
     * 
     * @return 性能指标
     */
    public PerformanceMetrics getCurrentPerformanceMetrics() {
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapMemory = memoryBean.getHeapMemoryUsage();
        MemoryUsage nonHeapMemory = memoryBean.getNonHeapMemoryUsage();
        
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        int threadCount = threadBean.getThreadCount();
        
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        long totalGcCount = 0;
        long totalGcTime = 0;
        
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            totalGcCount += gcBean.getCollectionCount();
            totalGcTime += gcBean.getCollectionTime();
        }
        
        long uptime = ManagementFactory.getRuntimeMXBean().getUptime();
        double gcTimePercent = uptime > 0 ? (double) totalGcTime / uptime * 100 : 0;
        
        return new PerformanceMetrics(
            heapMemory.getUsed(),
            heapMemory.getMax(),
            nonHeapMemory.getUsed(),
            threadCount,
            totalGcCount,
            totalGcTime,
            gcTimePercent,
            System.currentTimeMillis()
        );
    }

    /**
     * 分析性能并生成优化建议
     * 
     * @param metrics 性能指标
     * @return 优化建议列表
     */
    private List<OptimizationSuggestion> analyzePerformanceAndGenerateSuggestions(PerformanceMetrics metrics) {
        List<OptimizationSuggestion> suggestions = new java.util.ArrayList<>();
        
        // 内存使用率分析
        double heapUsagePercent = (double) metrics.getUsedHeapMemory() / metrics.getMaxHeapMemory() * 100;
        if (heapUsagePercent > 80) {
            suggestions.add(new OptimizationSuggestion(
                "MEMORY_OPTIMIZATION",
                "内存使用率过高",
                "建议增加堆内存大小或优化内存使用，当前使用率: " + String.format("%.2f", heapUsagePercent) + "%"
            ));
        }
        
        // GC性能分析
        if (metrics.getGcTimePercent() > 10) {
            suggestions.add(new OptimizationSuggestion(
                "GC_OPTIMIZATION",
                "GC时间占比过高",
                "建议优化GC配置或减少对象创建，当前GC时间占比: " + String.format("%.2f", metrics.getGcTimePercent()) + "%"
            ));
        }
        
        // 线程数分析
        if (metrics.getThreadCount() > 200) {
            suggestions.add(new OptimizationSuggestion(
                "THREAD_OPTIMIZATION",
                "线程数量过多",
                "建议优化线程池配置或减少并发线程数，当前线程数: " + metrics.getThreadCount()
            ));
        }
        
        // 非堆内存分析
        if (metrics.getUsedNonHeapMemory() > 100 * 1024 * 1024) { // 100MB
            suggestions.add(new OptimizationSuggestion(
                "NON_HEAP_MEMORY_OPTIMIZATION",
                "非堆内存使用过多",
                "建议检查元空间或代码缓存使用情况，当前非堆内存: " + (metrics.getUsedNonHeapMemory() / 1024 / 1024) + " MB"
            ));
        }
        
        return suggestions;
    }

    /**
     * 获取性能统计信息
     * 
     * @return 性能统计信息
     */
    public PerformanceStatistics getPerformanceStatistics() {
        return new PerformanceStatistics(
            totalGcCount.get(),
            totalGcTime.get(),
            totalCpuTime.get(),
            totalThreadCount.get()
        );
    }

    /**
     * 性能指标类
     */
    public static class PerformanceMetrics {
        private final long usedHeapMemory;
        private final long maxHeapMemory;
        private final long usedNonHeapMemory;
        private final int threadCount;
        private final long gcCount;
        private final long gcTime;
        private final double gcTimePercent;
        private final long timestamp;

        public PerformanceMetrics(long usedHeapMemory, long maxHeapMemory, long usedNonHeapMemory,
                                int threadCount, long gcCount, long gcTime, double gcTimePercent, long timestamp) {
            this.usedHeapMemory = usedHeapMemory;
            this.maxHeapMemory = maxHeapMemory;
            this.usedNonHeapMemory = usedNonHeapMemory;
            this.threadCount = threadCount;
            this.gcCount = gcCount;
            this.gcTime = gcTime;
            this.gcTimePercent = gcTimePercent;
            this.timestamp = timestamp;
        }

        // Getter方法
        public long getUsedHeapMemory() { return usedHeapMemory; }
        public long getMaxHeapMemory() { return maxHeapMemory; }
        public long getUsedNonHeapMemory() { return usedNonHeapMemory; }
        public int getThreadCount() { return threadCount; }
        public long getGcCount() { return gcCount; }
        public long getGcTime() { return gcTime; }
        public double getGcTimePercent() { return gcTimePercent; }
        public long getTimestamp() { return timestamp; }
        public double getHeapUsagePercent() { 
            return maxHeapMemory > 0 ? (double) usedHeapMemory / maxHeapMemory * 100 : 0; 
        }
    }

    /**
     * 优化建议类
     */
    public static class OptimizationSuggestion {
        private final String type;
        private final String title;
        private final String description;

        public OptimizationSuggestion(String type, String title, String description) {
            this.type = type;
            this.title = title;
            this.description = description;
        }

        // Getter方法
        public String getType() { return type; }
        public String getTitle() { return title; }
        public String getDescription() { return description; }
    }

    /**
     * 性能统计信息类
     */
    public static class PerformanceStatistics {
        private final long totalGcCount;
        private final long totalGcTime;
        private final long totalCpuTime;
        private final long totalThreadCount;

        public PerformanceStatistics(long totalGcCount, long totalGcTime, long totalCpuTime, long totalThreadCount) {
            this.totalGcCount = totalGcCount;
            this.totalGcTime = totalGcTime;
            this.totalCpuTime = totalCpuTime;
            this.totalThreadCount = totalThreadCount;
        }

        // Getter方法
        public long getTotalGcCount() { return totalGcCount; }
        public long getTotalGcTime() { return totalGcTime; }
        public long getTotalCpuTime() { return totalCpuTime; }
        public long getTotalThreadCount() { return totalThreadCount; }

        @Override
        public String toString() {
            return String.format("PerformanceStatistics{totalGcCount=%d, totalGcTime=%d, " +
                               "totalCpuTime=%d, totalThreadCount=%d}",
                               totalGcCount, totalGcTime, totalCpuTime, totalThreadCount);
        }
    }
}
